const {
	Service
} = require("uni-cloud-router");
const {
	result_success,
	result_error
} = require('http-result-modle')
const {
	payNotifyUrl
} = require('config-current-space')
const {
	mainSpaceId
} = require('config-main-space')
const db = uniCloud.database()
const {
	XMLParser
} = require("fast-xml-parser");
const crypto = require("crypto");
const mycloud = uniCloud.init({
	provider: 'tencent',
	spaceId: mainSpaceId
})
const wmzWechatSdk = mycloud.importObject('wmz-wechat-sdk')
module.exports = class WechatService extends(
	Service
) {
	async getWechatOpenId(app_id, code, templateId) {
		if (templateId) {
			let appletInfo = await this.service.applet.getAppletInfoByWechatId(templateId)
			let url = "https://api.weixin.qq.com/sns/jscode2session?"
			url = url + "appid=" + templateId
			url = url + "&secret=" + appletInfo.wechat.secret
			url = url + "&js_code=" + code
			url = url + "&grant_type='authorization_code'"
			let res = await wmzWechatSdk.wechatRequestCommon({
				url: url,
				method: 'GET'
			})
			if (res.code === 200) {
				return result_success(res.data)
			} else {
				return result_error(res.data.errmsg)
			}
		} else {
			let appletInfo = await this.service.applet.getAppletInfoById(app_id)
			let component_appid = appletInfo.wechat.app_id
			let appid = appletInfo.wechat.auth_app_id
			let componentToken = await wmzWechatSdk.getComponentToken(component_appid)
			if (componentToken.code === 200) {
				let url = "https://api.weixin.qq.com/sns/component/jscode2session?"
				url = url + "appid=" + appid
				url = url + "&js_code=" + code
				url = url + "&grant_type='authorization_code'"
				url = url + "&component_appid=" + component_appid
				url = url + "&component_access_token=" + componentToken.data
				let res = await wmzWechatSdk.wechatRequestCommon({
					url: url,
					method: 'GET'
				})
				if (res.code === 200) {
					return result_success(res.data)
				} else {
					return result_error(res.data.errmsg)
				}
			}
		}
	}

	/**
	 * 支付
	 * @param {Object} app_id 应用ID
	 * @param {Object} openid  openid
	 * @param {Object} out_trade_no  订单号
	 * @param {Object} total_fee  金额 单位分
	 * @param {Object} body  支付内容
	 * @param {Object} notify_url  通知地址
	 */
	async pay(app_id, openid, out_trade_no, total_fee, body, notify_url) {
		let data = await this.service.applet.getAppletInfoById(app_id)
		let appid = data.wechat.bind_appid
		let mch_id = data.wechat.mchid
		let res
		let sub_appid
		let key = "NaxuIB3FPyj5uLp8aSYZsv0TrgYuVaw1"
		if (!data.wechat.secret) {
			sub_appid = data.wechat.auth_app_id
			let sub_mch_id = data.wechat.sub_mchid
			if (!sub_mch_id) {
				let tdb = uniCloud.database({
					provider: 'tencent',
					spaceId: mainSpaceId
				})
				let tAppletInfo = await tdb.collection('wmz-applet-info').doc(app_id).get()
				tAppletInfo = tAppletInfo.data[0]
				sub_appid = tAppletInfo.wechat.sub_mchid
				if (!sub_appid) {
					return result_error("未配置商户号")
				}
				await db.collection('wmz-applet-info').doc(app_id).update({
					'wechat.sub_mchid': sub_appid
				})
			}
			let url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
			if (notify_url) {
				notify_url = payNotifyUrl + notify_url
			}
			let obj = {
				appid: appid,
				mch_id: mch_id,
				sub_appid: sub_appid,
				sub_mch_id: sub_mch_id,
				sub_openid: openid,
				nonce_str: this.get_nonce_str(32),
				notify_url: notify_url,
				out_trade_no: out_trade_no,
				spbill_create_ip: "127.0.0.1",
				total_fee: total_fee,
				trade_type: "JSAPI",
				fee_type: "CNY",
				body: body,
				profit_sharing: 'N'
			}
			if (data.wechat.profitsharing) {
				if (total_fee > 300) {
					obj.profit_sharing = 'Y'
				}
			} else {
				return result_error("支付权限错误")
			}
			let arr = Object.keys(obj).sort().map(item => {
				return `${item}=${obj[item]}`;
			});
			let str = arr.join('&') + '&key=' + key;
			let sign = this.getSign(str);
			res = await uniCloud.httpclient.request(url, {
				method: 'POST',
				data: '<xml>' +
					'<appid>' + obj.appid + '</appid>' +
					'<mch_id>' + obj.mch_id + '</mch_id>' +
					'<sub_appid>' + obj.sub_appid + '</sub_appid>' +
					'<sub_mch_id>' + obj.sub_mch_id + '</sub_mch_id>' +
					'<sub_openid>' + obj.sub_openid + '</sub_openid>' +
					'<nonce_str>' + obj.nonce_str + '</nonce_str>' +
					'<notify_url>' + obj.notify_url + '</notify_url>' +
					'<out_trade_no>' + obj.out_trade_no + '</out_trade_no>' +
					'<spbill_create_ip>' + obj.spbill_create_ip + '</spbill_create_ip>' +
					'<total_fee>' + obj.total_fee + '</total_fee>' +
					'<trade_type>' + obj.trade_type + '</trade_type>' +
					'<fee_type>' + obj.fee_type + '</fee_type>' +
					'<body>' + obj.body + '</body>' +
					'<profit_sharing>' + obj.profit_sharing + '</profit_sharing>' +
					'<sign>' + sign + '</sign>' +
					'</xml>',
				dataType: 'text' // 指定返回值为json格式，自动进行parse
			})
			console.log(res)
		}else{
			sub_appid=appid
			let url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
			if (notify_url) {
				notify_url = payNotifyUrl + notify_url
			}
			let obj = {
				appid: appid,
				mch_id: mch_id,
				openid: openid,
				nonce_str: this.get_nonce_str(32),
				notify_url: notify_url,
				out_trade_no: out_trade_no,
				spbill_create_ip: "127.0.0.1",
				total_fee: total_fee,
				trade_type: "JSAPI",
				fee_type: "CNY",
				body: body
			}
			let arr = Object.keys(obj).sort().map(item => {
				return `${item}=${obj[item]}`;
			});
			let str = arr.join('&') + '&key=' + key;
			let sign = this.getSign(str);
			res = await uniCloud.httpclient.request(url, {
				method: 'POST',
				data: '<xml>' +
					'<appid>' + obj.appid + '</appid>' +
					'<mch_id>' + obj.mch_id + '</mch_id>' +
					'<openid>' + obj.openid + '</openid>' +
					'<nonce_str>' + obj.nonce_str + '</nonce_str>' +
					'<notify_url>' + obj.notify_url + '</notify_url>' +
					'<out_trade_no>' + obj.out_trade_no + '</out_trade_no>' +
					'<spbill_create_ip>' + obj.spbill_create_ip + '</spbill_create_ip>' +
					'<total_fee>' + obj.total_fee + '</total_fee>' +
					'<trade_type>' + obj.trade_type + '</trade_type>' +
					'<fee_type>' + obj.fee_type + '</fee_type>' +
					'<body>' + obj.body + '</body>' +
					'<sign>' + sign + '</sign>' +
					'</xml>',
				dataType: 'text' // 指定返回值为json格式，自动进行parse
			})
			console.log(res)
		}	
		
		let xml = res.data
		const parser = new XMLParser();
		let rData = parser.parse(xml);
		rData = rData.xml
		if (rData.return_code === "SUCCESS") {
			if (rData.result_code === "SUCCESS") {
				let obj = {
					appId: sub_appid,
					timeStamp: new Date().getTime() + "",
					package: "prepay_id=" + rData.prepay_id,
					nonceStr: rData.nonce_str,
					signType: "MD5"
				}
				let arr = Object.keys(obj).sort().map(item => {
					return `${item}=${obj[item]}`;
				});
				let str = arr.join('&') + '&key=' + key;
				obj.paySign = this.getSign(str);
				/* if (!order.no_order_sync) {
					try{
						order.mchid=sub_mch_id
						order.wechatId=sub_appid
						let wechatSyncData=await this.service.order.javaOrderData(order,order.items[0].order_content)
						let wechatSyncResult = await cateringSumbit(wechatSyncData,"/order/wechatSync","POST")
					}catch(e){
						//TODO handle the exception
					}
				} */
				return result_success(obj)
			} else {
				return result_error(rData)
			}
		} else {
			return result_error(rData.return_msg)
		}
	}

	/**
	 * 对指定字符串进行md5加密
	 * @param {String} str 
	 */
	getSign(str) {
		let hash = crypto.createHash('md5').update(str, 'utf8');
		return hash.digest('hex').toUpperCase();
	}

	/**
	 * 生成指定长度的随机数
	 * @param {*int} len 
	 */
	get_nonce_str(len) {
		let str = '';
		while (str.length < len) {
			str += Math.random().toString(36).slice(2);
		}
		return str.slice(-len);
	}
};